package com.uziot.boot.annotions;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.Map;

/**
 * @author shidt
 * @version V1.0
 * @className RunnerApplication
 * @date 2021-10-09 10:56:32
 * @description
 */

public class ManualRegisterBeanUtils {

    /**
     * 主动向Spring容器中注册bean
     *
     * @param context Spring容器
     * @param name    BeanName
     * @param clazz   注册的bean的类性
     * @param args    构造方法的必要参数，顺序和类型要求和clazz中定义的一致
     * @param <T>     注册后的对象
     * @return 返回注册到容器中的bean对象
     */
    public static <T> T registerBean(ConfigurableApplicationContext context, String name, Class<T> clazz,
                                     Object... args) {
        if (context.containsBean(name)) {
            Object bean = context.getBean(name);
            if (bean.getClass().isAssignableFrom(clazz)) {
                return (T) bean;
            } else {
                throw new RuntimeException("BeanName 重复 " + name);
            }
        }

        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
        for (Object arg : args) {
            beanDefinitionBuilder.addConstructorArgValue(arg);
        }
        BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();

        BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry) context.getBeanFactory();
        beanFactory.registerBeanDefinition(name, beanDefinition);
        return context.getBean(name, clazz);
    }

    /**
     * 删除removeBeanDefinition 手动删除已注册的Bean
     *
     * @param context  context
     * @param beanName beanName
     */
    public void removeBeanDefinition(ConfigurableApplicationContext context, String beanName) {
        // 获取BeanFactory
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) context
                .getAutowireCapableBeanFactory();
        defaultListableBeanFactory.removeBeanDefinition(beanName);
    }
}
